<template>
  <div class="tool-bar">
    <div class="bar-btn">
      <div class="btn-item" v-for="(item, index) in btnList" :key="index" :class="{ 'is-select': item.isCheck }"
        @click="clickBtn(item)">
        <span>{{ item.name }}</span>
      </div>
    </div>

    <div class="bar-control">
      <div class="control-item" v-for="(item, index) in controlList" :key="index" :class="{ 'is-select': item.isCheck }">
        <div class="control-box" @click="clickControl(item)">
          <img :src="require(`@/assets/image/toolBar/${item.name}.png`)" alt="">
          <span>{{ item.name }}</span>
        </div>
      </div>
    </div>

    <path-roaming v-if="showRoaming" @close="closeRoaming"></path-roaming>
    <about-dialog v-if="showAbout" @close="closeAbout"></about-dialog>
  </div>
</template>

<script>
const fs = window.require('fs');
const { ipcRenderer } = window.require('electron');
import pathRoaming from '@/components/toolBar/pathRoaming';
import aboutDialog from '@/components/toolBar/aboutDialog';
export default {
  components: { pathRoaming, aboutDialog },

  data () {
    return {
      btnList: [
        {
          name: '开始',
          isCheck: true,
          controlList: [
            {
              name: '打开'
            },
            {
              name: '保存'
            },
            {
              name: '另存为'
            },
            {
              name: '退出'
            }
          ]
        },
        {
          name: '显示',
          isCheck: false,
          controlList: [
            {
              name: '纹理'
            },
            {
              name: '线框'
            },
            {
              name: '双面'
            },
            {
              name: '双屏对比'
            }
          ]
        },
        {
          name: '视图',
          isCheck: false,
          controlList: [
            {
              name: '前视图'
            },
            {
              name: '后视图'
            },
            {
              name: '左视图'
            },
            {
              name: '右视图'
            },
            {
              name: '俯视图'
            },
            {
              name: '路径漫游'
            }
          ]
        },
        {
          name: '帮助',
          isCheck: false,
          controlList: [
            {
              name: '帮助文档'
            },
            {
              name: '关于'
            }
          ]
        }
      ],
      controlList: [],
      openFileData: null,
      uploadFiles: [],
      showRoaming: false,
      showAbout: false
    };
  },

  methods: {
    // 按钮点击
    clickBtn (option) {
      if (option.isCheck) return;

      this.btnList.forEach(item => {
        item.isCheck = item.name == option.name ? true : false;
      });
      let controlList = this.btnList.find(e => { return e.isCheck; }).controlList;
      this.controlList = controlList;
    },

    // 控件点击
    clickControl (option) {
      const steadyLight = () => {
        let controlList = this.controlList;
        controlList.forEach(item => {
          if (item.name == option.name) {
            item.isCheck = !item.isCheck;
          }
        });
        this.controlList = [];
        this.controlList = controlList;
      };

      const flickerLight = () => {
        let controlList = this.controlList;
        setTimeout(() => {
          controlList.forEach(item => {
            if (item.name == option.name) {
              item.isCheck = false;
            }
            this.controlList = [];
            this.controlList = controlList;
          });
        }, 100);
      };

      switch (option.name) {
        case '纹理':
        case '线框':
        case '双面':
        case '双屏对比':
        case '路径漫游':
        case '量测':
        case '位置调整':
        case '日照':
          steadyLight();
          break;

        default:
          flickerLight();
          break;
      }

      switch (option.name) {
        case '打开':
          this.openFile();
          break;

        case '保存':
          this.saveFile();
          break;

        case '另存为':
          this.saveAsFile();
          break;

        case '退出':
          this.$confirm('确定退出', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            ipcRenderer.send('app-exit');
          });
          break;

        case '纹理':
          this.modelTexture(option.isCheck);
          break;

        case '线框':
          this.modelWireframe(option.isCheck);
          break;

        case '双面':
          this.modelBackFaceCulling(option.isCheck);
          break;

        case '双屏对比':
          this.$emit('clickControl', { name: option.name, isCheck: option.isCheck });
          break;


        case '前视图':
        case '后视图':
        case '左视图':
        case '右视图':
        case '俯视图':
        case '仰视图':
          this.switchView(option.name);
          break;

        case '路径漫游':
          this.showRoaming = option.isCheck;
          break;

        case '关于':
          this.showAbout = true;
          break;

        default:
          break;
      }
    },

    /**
     * 开始
    */
    // 打开
    openFile () {
      ipcRenderer.send('show-open-dialog');
      ipcRenderer.on('show-open-dialog', (event, data) => {
        const { filePath, fileSize, fileContent } = data;
        if (!filePath) {
          return;
        } else if (!fileContent) {
          this.message('文件为空');
          return;
        } else if (fileSize > 10) {
          this.message('文件大小超过10MB');
          return;
        }
        const info = JSON.parse(fileContent);
        if (info.type != '3dViewer') {
          this.message('请选择 type为 3dViewer的文件');
          return;
        }
        this.eventBus.$emit('loadFile', info.data);
        window.sessionStorage.setItem('openFileData', JSON.stringify(data));
      });
    },

    // 保存文件
    saveFile () {
      let openFileData = window.sessionStorage.getItem('openFileData');
      if (openFileData) {
        const fileData = JSON.parse(openFileData);
        const { filePath } = fileData;
        if (!fs.existsSync(filePath)) {
          this.saveAsFile();
          return;
        }
        const fileContent = this.getSaveContent();
        if (!fileContent) {
          this.saveAsFile();
          return;
        }
        fs.writeFileSync(filePath, fileContent);
        this.message('保存成功', 'success');
      } else {
        this.saveAsFile();
      }
    },

    // 另存为
    saveAsFile () {
      const fileContent = this.getSaveContent();
      ipcRenderer.send('show-save-dialog', { fileContent: fileContent });
      ipcRenderer.on('show-save-dialog', (event, data) => {
        window.sessionStorage.setItem('openFileData', JSON.stringify(data));
        this.message('另存成功', 'success');
      });
    },

    getSaveContent () {
      this.eventBus.$emit('getTreeData');
      let treeData = JSON.parse(JSON.stringify(this.Global.treeData));
      let fileContent = null;
      if (this.viewer) {
        let content = {
          type: '3dViewer',
          data: treeData
        };
        fileContent = JSON.stringify(content);
        console.log(content);
      }
      return fileContent;
    },

    /**
     * 显示
     * */
    // 纹理
    modelTexture (state) {
      if (!this.viewer || !this.viewer.scene.primitives || !this.viewer.scene.primitives._primitives || !this.viewer.scene.primitives._primitives.length) return;
      let tilePrimitives = this.viewer.scene.primitives._primitives.filter(e => { return e instanceof Cesium.Cesium3DTileset; });
      if (!tilePrimitives.length) return;
      this.createdCustomShader();
      tilePrimitives.forEach(item => {
        item.customShader = state ? this.customShader : null;
      });
    },

    createdCustomShader () {
      if (this.customShader) return;
      this.customShader = new Cesium.CustomShader({
        // lightingModel: Cesium.LightingModel.UNLIT,
        //  lightingModel: Cesium.LightingModel.PBR,
        // 设置变量，由顶点着色器传递给片元着色器
        varyings: {
          v_normalMC: Cesium.VaryingType.VEC3,
          v_st: Cesium.VaryingType.VEC3
        },
        // 外部传给顶点着色器或者片元着色器
        uniforms: {
          u_texture: {
            value: new Cesium.TextureUniform({
              url: require('@/assets/image/toolBar/R-C2.jpg')
            }),
            type: Cesium.UniformType.SAMPLER_2D
          }
        },
        // 贴纹理
        // 顶点着色器
        // 将法向量从顶点着色器设置变量传给片元着色器
        vertexShaderText: `
            void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
                  v_normalMC = vsInput.attributes.normalMC;
                  v_st=vsInput.attributes.positionMC;   
            }`,
        // 片元着色器
        fragmentShaderText: `
           void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
              vec3 positionMC = fsInput.attributes.positionMC;
              // 这里是设置要贴图的图片的尺寸，设置小了会重复
              float width = 37.0;
              float height = 40.0;
              vec3 rgb;
              // 这是是设置了屋顶的颜色，当和法向量平行时，就是屋顶，这里设置0.95，相当于垂直，建筑物四周开始贴图
              if (dot(vec3(0.0, 1.0, 0.0), v_normalMC) > 0.95) {
                material.diffuse = vec3(1.0, 0.0, 0.0);
              } else {
                float textureX = 0.0;
                float dotYAxis = dot(vec3(0.0, 0.0, 1.0), v_normalMC);
                // cos(45deg) 约等于 0.71，这里是建筑物四周的向量与法向量会大于四十五度夹角
                if (dotYAxis > 0.71 || dotYAxis < -0.71) {
                // x代表的是前后面
                  textureX = mod(positionMC.x, width) / width;
                } else {
                // z代表的是左右面
                  textureX = mod(positionMC.z, width) / width;
                }
                float textureY = mod(positionMC.y, height) / height;
                rgb = texture2D(u_texture, vec2(textureX, textureY)).rgb;
                material.diffuse = rgb;
              }
          }`
      });
    },

    // 线框
    modelWireframe (state) {
      if (!this.viewer || !this.viewer.scene.primitives || !this.viewer.scene.primitives._primitives || !this.viewer.scene.primitives._primitives.length) return;
      let tilePrimitives = this.viewer.scene.primitives._primitives.filter(e => { return e instanceof Cesium.Cesium3DTileset; });
      if (!tilePrimitives.length) return;
      tilePrimitives.forEach(item => {
        item.debugShowBoundingVolume = state;
      });
    },

    // 双面
    modelBackFaceCulling (state) {
      if (!this.viewer || !this.viewer.scene.primitives || !this.viewer.scene.primitives._primitives || !this.viewer.scene.primitives._primitives.length) return;
      let tilePrimitives = this.viewer.scene.primitives._primitives.filter(e => { return e instanceof Cesium.Cesium3DTileset; });
      if (!tilePrimitives.length) return;
      tilePrimitives.forEach(item => {
        item.backFaceCulling = state;
      });
    },

    /**
     * 视图
     * */
    switchView (option) {
      const viewPosition = this.getViewer();
      let orientation = {};
      switch (option) {
        case '前视图':
          orientation = {
            heading: 0,
            pitch: 0,
            roll: 0
          };
          break;

        case '后视图':
          orientation = {
            heading: 180,
            pitch: 0,
            roll: 0
          };
          break;

        case '左视图':
          orientation = {
            heading: 270,
            pitch: 0,
            roll: 0
          };
          break;

        case '右视图':
          orientation = {
            heading: 90,
            pitch: 0,
            roll: 0
          };
          break;

        case '俯视图':
          orientation = {
            heading: 0,
            pitch: -90,
            roll: 0
          };
          break;

        case '仰视图':
          orientation = {
            heading: 180,
            pitch: 90,
            roll: 0
          };
          break;

        default:
          break;
      }
      this.flyTo({ ...viewPosition.position, ...orientation });
    },

    getViewer () {
      const viewer = this.viewer;
      let cartesian = viewer.camera.position.clone();
      let ellipsoid = this.viewer.scene.globe.ellipsoid;
      let cartographic = ellipsoid.cartesianToCartographic(cartesian);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let height = cartographic.height;
      return {
        cartesian,
        position: { lat, lng, height },
        orientation: {
          heading: viewer.camera.heading,
          pitch: viewer.camera.pitch,
          roll: viewer.camera.roll
        }
      };
    },

    flyTo (position, callback) {
      const { lng, lat, height, heading, pitch, roll } = position;
      if (!lng || !lat || !height) return;
      this.viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(lng, lat, height),
        orientation: { heading: Cesium.Math.toRadians(heading), pitch: Cesium.Math.toRadians(pitch), roll: Cesium.Math.toRadians(roll) },
        complete: callback && callback()
      });
    },

    closeRoaming () {
      this.showRoaming = false;
      let btnList = this.btnList;
      btnList.forEach(item => {
        if (item.name == '视图') {
          item.controlList.map(e => { return e.name == '路径漫游' && (e.isCheck = false); });
        }
      });
      this.btnList = btnList;
    },

    /**
     * 帮助
     * */
    closeAbout () {
      this.showAbout = false;
    },

    // 提示
    message (message = '警告', type = 'warning') {
      this.$message({
        message: message,
        type: type
      });
    }
  },

  created () {
    this.controlList = this.btnList.find(e => { return e.isCheck; }).controlList;
    this.customShader = null;
  },

  mounted () {
    this.viewer = this.Global.viewer;
  },

  beforeDestroy () {
    this.customShader = null;
    window.sessionStorage.setItem('openFileData', '');
    this.modelTexture(false);
    this.modelWireframe(false);
  }
}
</script>

<style lang="less" scoped>
.tool-bar {
  width: 100%;
  height: 100%;

  .bar-btn {
    display: flex;
    align-items: center;
    height: 30px;

    .btn-item {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 62px;
      height: 100%;
      font-size: 14px;
      color: #ffffff;
      cursor: pointer;
    }

    .is-select {
      background: #444444;
      border-radius: 4px 4px 0px 0px;
    }
  }

  .bar-control {
    display: flex;
    align-items: center;
    height: 64px;
    border-top: 1px solid #444444;

    .control-item {
      width: 62px;
      height: 100%;
      cursor: pointer;

      &:hover {
        background: rgba(74, 88, 120, 0.4);
      }

      img {
        width: 28px;
        height: 28px;
        margin-bottom: 6px;
      }

      .control-box,
      /deep/.upload-btn,
      /deep/.el-upload {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        width: 100%;
        height: 100%;
        font-size: 12px;
        color: #ffffff !important;
      }
    }

    .is-select {
      background: rgba(74, 88, 120, 0.4);
    }
  }
}
</style>